home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 1 / QRZ Ham Radio Callsign Database - December 1993.iso / ucsd / packet / tcpip / sys5 / iscwmpst.z / iscwmpst / tcp / isc-src / util / udbm.c < prev   
Encoding:
C/C++ Source or Header  |  1991-10-29  |  17.9 KB  |  737 lines

  1. /* User Data Base Manager */
  2.  
  3. static char  rcsid[] = "@(#) $Header: udbm.c,v 1.10 91/04/16 13:17:07 deyke Exp $";
  4.  
  5. #define DEBUG           0
  6.  
  7. #define _HPUX_SOURCE    1
  8.  
  9. #include <sys/types.h>
  10.  
  11. #include <ctype.h>
  12. #include <errno.h>
  13. #include <fcntl.h>
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include <string.h>
  17. #include <sys/stat.h>
  18.  
  19.  
  20. #ifdef __TURBOC__
  21.  
  22. #include <alloc.h>
  23. #include <dos.h>
  24. #include <io.h>
  25.  
  26. struct utsname {
  27.   char  nodename[16];
  28. };
  29.  
  30. struct passwd {
  31.   char  *pw_name;
  32.   char  *pw_gecos;
  33. };
  34.  
  35. #else
  36.  
  37. #include <pwd.h>
  38. #include <sys/utsname.h>
  39. #include <unistd.h>
  40.  
  41. #endif
  42.  
  43. #if (defined(__STDC__) || defined(__TURBOC__))
  44. #define __ARGS(x)       x
  45. #else
  46. #define __ARGS(x)       ()
  47. #endif
  48. #define const
  49.  
  50. struct user {
  51.   struct user *next;
  52.   const char *call;
  53.   const char *name;
  54.   const char *street;
  55.   const char *city;
  56.   const char *qth;
  57.   const char *phone;
  58.   const char *mail;
  59.   char alias;
  60. };
  61.  
  62. #define NUM_USERS 2503
  63.  
  64. #if DEBUG
  65. static char usersfile[] = "users";
  66. static char userstemp[] = "users.tmp";
  67. static char indexfile[] = "index";
  68. static char passfile[]  = "passwd";
  69. static char passtemp[]  = "ptmp";
  70. static char aliasfile[] = "aliases";
  71. static char aliastemp[] = "aliases.tmp";
  72. #else
  73. static char usersfile[] = "/usr/local/lib/users";
  74. static char userstemp[] = "/usr/local/lib/users.tmp";
  75. static char indexfile[] = "/users/bbs/index";
  76. static char passfile[]  = "/etc/passwd";
  77. static char passtemp[]  = "/etc/ptmp";
  78. static char aliasfile[] = "/usr/lib/aliases";
  79. static char aliastemp[] = "/usr/lib/aliases.tmp";
  80. #endif
  81.  
  82. static const char *lockfile;
  83. static const char *null_string = "";
  84. static long  heapsize;
  85. static struct user *users[NUM_USERS];
  86. static struct user null_user;
  87. static struct utsname uts_name;
  88.  
  89. int uname __ARGS((struct utsname *name));
  90. struct passwd *getpwent __ARGS((void));
  91. void endpwent __ARGS((void));
  92. int putpwent __ARGS((struct passwd *p, FILE *f));
  93. static void terminate __ARGS((const char *s));
  94. static void *allocate __ARGS((size_t size));
  95. static int calc_crc __ARGS((const char *str));
  96. static const char *strsave __ARGS((const char *s));
  97. static char *strlwc __ARGS((char *s));
  98. static char *rmspaces __ARGS((char *s));
  99. static char *strtrim __ARGS((char *s));
  100. static int is_call __ARGS((const char *s));
  101. static int is_qth __ARGS((const char *s));
  102. static int is_phone __ARGS((const char *s));
  103. static int is_mail __ARGS((const char *s));
  104. static int join __ARGS((const char **s1, const char **s2));
  105. static struct user *getup __ARGS((const char *call, int create));
  106. static FILE *fopenexcl __ARGS((const char *path));
  107. static void output_line __ARGS((const struct user *up, FILE *fp));
  108. static int fixusers __ARGS((void));
  109. static void fixpasswd __ARGS((void));
  110. static void fixaliases __ARGS((void));
  111. int main __ARGS((void));
  112.  
  113. #ifdef __TURBOC__
  114.  
  115. unsigned  _stklen = 10240;
  116.  
  117. int  uname(struct utsname *name)
  118. {
  119.   strcpy(name->nodename, "db0sao");
  120.   return 0;
  121. }
  122.  
  123. struct passwd *getpwent(void)
  124. {
  125.   return NULL;
  126. }
  127.  
  128. void endpwent(void)
  129. {
  130. }
  131.  
  132. int  putpwent(struct passwd *p, FILE *f)
  133. {
  134.   return 0;
  135. }
  136.  
  137. #endif
  138.  
  139. /*---------------------------------------------------------------------------*/
  140.  
  141. static void terminate(s)
  142. const char *s;
  143. {
  144.   perror(s);
  145.   if (lockfile) unlink(lockfile);
  146.   exit(1);
  147. }
  148.  
  149. /*---------------------------------------------------------------------------*/
  150.  
  151. #define uchar(c)  ((unsigned char) (c))
  152.  
  153. /*---------------------------------------------------------------------------*/
  154.  
  155. static void *allocate(size)
  156. size_t size;
  157. {
  158.  
  159.   static char  *freespace;
  160.   static size_t allocsize = 64*1024-2;
  161.   static size_t freesize;
  162.   void * p;
  163.  
  164.   if (size & 1) size++;
  165.   if (size > freesize) {
  166.     for (; ; ) {
  167. #ifdef __TURBOC__
  168.       fprintf(stderr, "size = %u coreleft = %lu allocsize = %u\n",
  169.               size, coreleft(), allocsize);
  170. #endif
  171.       if (size > allocsize) {
  172.         errno = ENOMEM;
  173.         terminate("allocate()");
  174.       }
  175.       if ((freespace = malloc(allocsize)) != NULL) {
  176.         freesize = allocsize;
  177.         heapsize += allocsize;
  178.         break;
  179.       }
  180.       allocsize >>= 1;
  181.     }
  182.   }
  183.   p = freespace;
  184.   freespace += size;
  185.   freesize -= size;
  186.   return p;
  187. }
  188.  
  189. /*---------------------------------------------------------------------------*/
  190.  
  191. /* Calculate crc16 for a null terminated string (used for hashing) */
  192.  
  193. static int  calc_crc(str)
  194. const char *str;
  195. {
  196.  
  197.   static const int crc_table[] = {
  198.     0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 0x0280, 0xc241,
  199.     0xc601, 0x06c0, 0x0780, 0xc741, 0x0500, 0xc5c1, 0xc481, 0x0440,
  200.     0xcc01, 0x0cc0, 0x0d80, 0xcd41, 0x0f00, 0xcfc1, 0xce81, 0x0e40,
  201.     0x0a00, 0xcac1, 0xcb81, 0x0b40, 0xc901, 0x09c0, 0x0880, 0xc841,
  202.     0xd801, 0x18c0, 0x1980, 0xd941, 0x1b00, 0xdbc1, 0xda81, 0x1a40,
  203.     0x1e00, 0xdec1, 0xdf81, 0x1f40, 0xdd01, 0x1dc0, 0x1c80, 0xdc41,
  204.     0x1400, 0xd4c1, 0xd581, 0x1540, 0xd701, 0x17c0, 0x1680, 0xd641,
  205.     0xd201, 0x12c0, 0x1380, 0xd341, 0x1100, 0xd1c1, 0xd081, 0x1040,
  206.     0xf001, 0x30c0, 0x3180, 0xf141, 0x3300, 0xf3c1, 0xf281, 0x3240,
  207.     0x3600, 0xf6c1, 0xf781, 0x3740, 0xf501, 0x35c0, 0x3480, 0xf441,
  208.     0x3c00, 0xfcc1, 0xfd81, 0x3d40, 0xff01, 0x3fc0, 0x3e80, 0xfe41,
  209.     0xfa01, 0x3ac0, 0x3b80, 0xfb41, 0x3900, 0xf9c1, 0xf881, 0x3840,
  210.     0x2800, 0xe8c1, 0xe981, 0x2940, 0xeb01, 0x2bc0, 0x2a80, 0xea41,
  211.     0xee01, 0x2ec0, 0x2f80, 0xef41, 0x2d00, 0xedc1, 0xec81, 0x2c40,
  212.     0xe401, 0x24c0, 0x2580, 0xe541, 0x2700, 0xe7c1, 0xe681, 0x2640,
  213.     0x2200, 0xe2c1, 0xe381, 0x2340, 0xe101, 0x21c0, 0x2080, 0xe041,
  214.     0xa001, 0x60c0, 0x6180, 0xa141, 0x6300, 0xa3c1, 0xa281, 0x6240,
  215.     0x6600, 0xa6c1, 0xa781, 0x6740, 0xa501, 0x65c0, 0x6480, 0xa441,
  216.     0x6c00, 0xacc1, 0xad81, 0x6d40, 0xaf01, 0x6fc0, 0x6e80, 0xae41,
  217.     0xaa01, 0x6ac0, 0x6b80, 0xab41, 0x6900, 0xa9c1, 0xa881, 0x6840,
  218.     0x7800, 0xb8c1, 0xb981, 0x7940, 0xbb01, 0x7bc0, 0x7a80, 0xba41,
  219.     0xbe01, 0x7ec0, 0x7f80, 0xbf41, 0x7d00, 0xbdc1, 0xbc81, 0x7c40,
  220.     0xb401, 0x74c0, 0x7580, 0xb541, 0x7700, 0xb7c1, 0xb681, 0x7640,
  221.     0x7200, 0xb2c1, 0xb381, 0x7340, 0xb101, 0x71c0, 0x7080, 0xb041,
  222.     0x5000, 0x90c1, 0x9181, 0x5140, 0x9301, 0x53c0, 0x5280, 0x9241,
  223.     0x9601, 0x56c0, 0x5780, 0x9741, 0x5500, 0x95c1, 0x9481, 0x5440,
  224.     0x9c01, 0x5cc0, 0x5d80, 0x9d41, 0x5f00, 0x9fc1, 0x9e81, 0x5e40,
  225.     0x5a00, 0x9ac1, 0x9b81, 0x5b40, 0x9901, 0x59c0, 0x5880, 0x9841,
  226.     0x8801, 0x48c0, 0x4980, 0x8941, 0x4b00, 0x8bc1, 0x8a81, 0x4a40,
  227.     0x4e00, 0x8ec1, 0x8f81, 0x4f40, 0x8d01, 0x4dc0, 0x4c80, 0x8c41,
  228.     0x4400, 0x84c1, 0x8581, 0x4540, 0x8701, 0x47c0, 0x4680, 0x8641,
  229.     0x8201, 0x42c0, 0x4380, 0x8341, 0x4100, 0x81c1, 0x8081, 0x4040
  230.   };
  231.  
  232.   int  crc;
  233.  
  234.   crc = 0;
  235.   while (*str)
  236.     crc = ((crc >> 8) & 0xff) ^ crc_table[(crc ^ *str++) & 0xff];
  237.   return crc;
  238. }
  239.  
  240. /*---------------------------------------------------------------------------*/
  241.  
  242. static const char *strsave(s)
  243. const char *s;
  244. {
  245.  
  246. #define NUM_STRINGS 4999
  247.  
  248.   struct strings {
  249.     struct strings *next;
  250.     char  s[1];
  251.   };
  252.  
  253.   int  hash;
  254.   static struct strings *strings[NUM_STRINGS];
  255.   struct strings *p;
  256.  
  257.   if (!*s) return null_string;
  258.   for (p = strings[hash = ((calc_crc(s) & 0x7fff) % NUM_STRINGS)];
  259.        p && strcmp(s, p->s);
  260.        p = p->next)
  261.     ;
  262.   if (!p) {
  263.     p = allocate(sizeof(struct strings *) + strlen(s) + 1);
  264.     strcpy(p->s, s);
  265.     p->next = strings[hash];
  266.     strings[hash] = p;
  267.   }
  268.   return p->s;
  269. }
  270.  
  271. /*---------------------------------------------------------------------------*/
  272.  
  273. static char  *strlwc(s)
  274. char  *s;
  275. {
  276.   char  *p;
  277.  
  278.   for (p = s; (*p = tolower(uchar(*p))) != 0; p++) ;
  279.   return s;
  280. }
  281.  
  282. /*---------------------------------------------------------------------------*/
  283.  
  284. static char  *rmspaces(s)
  285. char  *s;
  286. {
  287.   char  *f, *t;
  288.  
  289.   for (f = t = s; *f; f++)
  290.     if (*f != ' ') *t++ = *f;
  291.   *t = '\0';
  292.   return s;
  293. }
  294.  
  295. /*---------------------------------------------------------------------------*/
  296.  
  297. static char  *strtrim(s)
  298. char  *s;
  299. {
  300.   char  *p;
  301.  
  302.   for (p = s; *p; p++) ;
  303.   while (--p >= s && *p == ' ') ;
  304.   p[1] = '\0';
  305.   return s;
  306. }
  307.  
  308. /*---------------------------------------------------------------------------*/
  309.  
  310. static int  is_call(s)
  311. const char *s;
  312. {
  313.   int  d, l;
  314.  
  315.   l = strlen(s);
  316.   if (l < 4 || l > 6) return 0;
  317.   if (!isalpha(uchar(s[l-1]))) return 0;
  318.   for (d = 0; *s; s++) {
  319.     if (!isalnum(uchar(*s))) return 0;
  320.     if (isdigit(uchar(*s))) d++;
  321.   }
  322.   return (d >= 1 && d <= 2);
  323. }
  324.  
  325. /*---------------------------------------------------------------------------*/
  326.  
  327. static int  is_qth(s)
  328. const char *s;
  329. {
  330.   switch (strlen(s)) {
  331.   case 5:
  332.     if ((s[0] >= 'A' && s[0] <= 'Z' || s[0] >= 'a' && s[0] <= 'z') &&
  333.         (s[1] >= 'A' && s[1] <= 'Z' || s[1] >= 'a' && s[1] <= 'z') &&
  334.         (s[2] >= '0' && s[2] <= '8'                              ) &&
  335.         (s[3] >= '0' && s[3] <= '9'                              ) &&
  336.         (s[4] >= 'A' && s[4] <= 'J' || s[4] >= 'a' && s[4] <= 'j') &&
  337.          s[4] != 'I' && s[4] != 'i')
  338.       return 1;
  339.     break;
  340.   case 6:
  341.     if ((s[0] >= 'A' && s[0] <= 'R' || s[0] >= 'a' && s[0] <= 'r') &&
  342.         (s[1] >= 'A' && s[1] <= 'R' || s[1] >= 'a' && s[1] <= 'r') &&
  343.         (s[2] >= '0' && s[2] <= '9'                              ) &&
  344.         (s[3] >= '0' && s[3] <= '9'                              ) &&
  345.         (s[4] >= 'A' && s[4] <= 'X' || s[4] >= 'a' && s[4] <= 'x') &&
  346.         (s[5] >= 'A' && s[5] <= 'X' || s[5] >= 'a' && s[5] <= 'x'))
  347.       return 1;
  348.     break;
  349.   }
  350.   return 0;
  351. }
  352.  
  353. /*---------------------------------------------------------------------------*/
  354.  
  355. static int  is_phone(s)
  356. const char *s;
  357. {
  358.   int  slash;
  359.  
  360.   for (slash = 0; *s; s++)
  361.     if (*s == '/')
  362.       slash++;
  363.     else if (!isdigit(uchar(*s)))
  364.       return 0;
  365.   return (slash == 1);
  366. }
  367.  
  368. /*---------------------------------------------------------------------------*/
  369.  
  370. static int  is_mail(s)
  371. const char *s;
  372. {
  373.   return (int) (strchr(s, '@') != NULL);
  374. }
  375.  
  376. /*---------------------------------------------------------------------------*/
  377.  
  378. static int  join(s1, s2)
  379. const char **s1, **s2;
  380. {
  381.   if (s1 == s2) return 0;
  382.   if (*s1 == null_string || strstr(*s2, *s1)) {
  383.     *s1 = *s2;
  384.     return 0;
  385.   }
  386.   if (*s2 == null_string || strstr(*s1, *s2)) {
  387.     *s2 = *s1;
  388.     return 0;
  389.   }
  390.   return 1;
  391. }
  392.  
  393. /*---------------------------------------------------------------------------*/
  394.  
  395. static struct user *getup(call, create)
  396. const char *call;
  397. int  create;
  398. {
  399.  
  400.   int  hash;
  401.   struct user *up;
  402.  
  403.   for (up = users[hash = ((calc_crc(call) & 0x7fff) % NUM_USERS)];
  404.        up && strcmp(call, up->call);
  405.        up = up->next)
  406.     ;
  407.   if (create && !up) {
  408.     up = allocate(sizeof(*up));
  409.     *up = null_user;
  410.     up->call = strsave(call);
  411.     up->next = users[hash];
  412.     users[hash] = up;
  413.   }
  414.   return up;
  415. }
  416.  
  417. /*---------------------------------------------------------------------------*/
  418.  
  419. static FILE *fopenexcl(path)
  420. const char *path;
  421. {
  422.  
  423.   FILE * fp;
  424.   int  fd, try;
  425.  
  426.   for (try = 1; ; try++) {
  427.     if ((fd = open(path, O_WRONLY | O_CREAT | O_EXCL, 0644)) >= 0) break;
  428.     if (try >= 10) terminate(path);
  429.     sleep(try);
  430.   }
  431.   lockfile = path;
  432.   fp = fdopen(fd, "w");
  433.   if (!fp) terminate(path);
  434.   return fp;
  435. }
  436.  
  437. /*---------------------------------------------------------------------------*/
  438.  
  439. static void output_line(up, fp)
  440. const struct user *up;
  441. FILE *fp;
  442. {
  443.  
  444. #define append(s)                    \
  445.   if (*(s)) {                        \
  446.     if (*line) {                     \
  447.       *t++ = ',';                    \
  448.       *t++ = ' ';                    \
  449.     }                                \
  450.     for (f = (s); *f; *t++ = *f++) ; \
  451.   }
  452.  
  453.   char line[1024];
  454.   const char *f;
  455.   char *t;
  456.  
  457.   t = line;
  458.   *t = '\0';
  459.   append(up->call);
  460.   append(up->name);
  461.   append(up->street);
  462.   append(up->city);
  463.   append(up->qth);
  464.   append(up->phone);
  465.   append(up->mail);
  466.   *t = '\0';
  467.   fputs(line, fp);
  468.   putc('\n', fp);
  469. }
  470.  
  471. /*---------------------------------------------------------------------------*/
  472.  
  473. static int  fixusers()
  474. {
  475.  
  476. #define NF 20
  477.  
  478. #define LEN_BID     12
  479. #define LEN_SUBJECT 80
  480. #define LEN_TO      8
  481. #define LEN_AT      8
  482. #define LEN_FROM    8
  483.  
  484.   struct index {
  485.     long  size;
  486.     long  date;
  487.     int  mesg;
  488.     char  bid[LEN_BID+1];
  489.     char  lifetime_h;
  490.     char  subject[LEN_SUBJECT+1];
  491.     char  lifetime_l;
  492.     char  to[LEN_TO+1];
  493.     char  at[LEN_AT+1];
  494.     char  from[LEN_FROM+1];
  495.     char  deleted;
  496.   };
  497.  
  498.   FILE *fpi, *fpo;
  499.   char  *f, *t;
  500.   char  *field[NF];
  501.   char  line[1024], orig_line[1024], mybbs[1024];
  502.   int  errors = 0;
  503.   int  i, nf, timestamp;
  504.   struct index index;
  505.   struct user *up;
  506.   struct user user;
  507.  
  508.   if (!(fpi = fopen(usersfile, "r"))) terminate(usersfile);
  509.   fpo = fopenexcl(userstemp);
  510.   while (fgets(line, sizeof(line), fpi)) {
  511.     for (f = line; *f; f++)
  512.       if (isspace(uchar(*f))) *f = ' ';
  513.     for (t = f = line; *f; f++)
  514.       if (*f != ' ' || f[1] != ' ') *t++ = *f;
  515.     if (t > line && t[-1] == ' ') t--;
  516.     *t = '\0';
  517.     strcpy(orig_line, line);
  518.     f = line;
  519.     memset(field, 0 , sizeof(field));
  520.     nf = 0;
  521.     user = null_user;
  522.     for (; ; ) {
  523.       while (*f && (*f == ' ' || *f == ',')) f++;
  524.       if (!*f) break;
  525.       field[nf++] = f;
  526.       f = strchr(f, ',');
  527.       if (f)
  528.         *f++ = '\0';
  529.       else
  530.         f = "";
  531.       strtrim(field[nf-1]);
  532.     }
  533.     if (!nf) continue;
  534.     for (i = 0; i < NF; i++)
  535.       if (field[i]) {
  536.         if (!*user.call && is_call(field[i])) {
  537.           user.call = strsave(strlwc(field[i]));
  538.           field[i] = NULL;
  539.           nf--;
  540.         } else if (!*user.qth && is_qth(field[i])) {
  541.           user.qth = strsave(strlwc(field[i]));
  542.           field[i] = NULL;
  543.           nf--;
  544.         } else if (!*user.phone && is_phone(field[i])) {
  545.           user.phone = strsave(field[i]);
  546.           field[i] = NULL;
  547.           nf--;
  548.         } else if (!*user.mail && is_mail(field[i])) {
  549.           user.mail = strsave(strlwc(rmspaces(field[i])));
  550.           field[i] = NULL;
  551.           nf--;
  552.         }
  553.       }
  554.     if (nf)
  555.       for (i = 0; i < NF; i++)
  556.         if (field[i]) {
  557.           user.name = strsave(field[i]);
  558.           field[i] = NULL;
  559.           nf--;
  560.           break;
  561.         }
  562.     if (nf >= 2)
  563.       for (i = 0; i < NF; i++)
  564.         if (field[i]) {
  565.           user.street = strsave(field[i]);
  566.           field[i] = NULL;
  567.           nf--;
  568.           break;
  569.         }
  570.     if (nf)
  571.       for (i = 0; i < NF; i++)
  572.         if (field[i]) {
  573.           user.city = strsave(field[i]);
  574.           field[i] = NULL;
  575.           nf--;
  576.           break;
  577.         }
  578.     if (nf) {
  579.       errors++;
  580.       fprintf(stderr, "***** Too many fields *****\n%s\n\n", orig_line);
  581.       fputs(orig_line, fpo);
  582.       putc('\n', fpo);
  583.       continue;
  584.     }
  585.     if (!*user.call) {
  586.       fputs(orig_line, fpo);
  587.       putc('\n', fpo);
  588.       continue;
  589.     }
  590.     up = getup(user.call, 1);
  591.     if (join(&up->name, &user.name)     |
  592.         join(&up->street, &user.street) |
  593.         join(&up->city, &user.city)     |
  594.         join(&up->qth, &user.qth)       |
  595.         join(&up->phone, &user.phone)   |
  596.         join(&up->mail, &user.mail)) {
  597.       errors++;
  598.       fprintf(stderr, "***** Join failed *****\n%s\n\n", orig_line);
  599.       output_line(&user, fpo);
  600.     }
  601.   }
  602.   fclose(fpi);
  603.  
  604.   if ((fpi = fopen(indexfile, "r")) != NULL) {
  605.     while (fread((char *) &index, sizeof(index), 1, fpi))
  606.       if (index.to[0] == 'M' && index.to[1] == '\0'              &&
  607.           !strcmp(index.at, "THEBOX")                            &&
  608.           is_call(index.from)                                    &&
  609.           sscanf(index.subject, "%s %d", mybbs, ×tamp) == 2 &&
  610.           is_call(mybbs)) {
  611.         up = getup(strlwc(index.from), 1);
  612.         *line = '@';
  613.         strcpy(line+1, strlwc(mybbs));
  614.         up->mail = strsave(line);
  615.       }
  616.     fclose(fpi);
  617.   }
  618.  
  619.   if (is_call(uts_name.nodename)) {
  620.     up = getup(uts_name.nodename, 1);
  621.     *line = '@';
  622.     strcpy(line+1, up->call);
  623.     up->mail = strsave(line);
  624.   }
  625.  
  626.   for (i = 0; i < NUM_USERS; i++)
  627.     for (up = users[i]; up; up = up->next) output_line(up, fpo);
  628.   fclose(fpo);
  629.  
  630. #ifdef __TURBOC__
  631.   unlink(usersfile);
  632. #endif
  633.   unlink(usersfile);
  634.   if (rename(userstemp, usersfile)) terminate(usersfile);
  635.   lockfile = NULL;
  636.   return errors;
  637. }
  638.  
  639. /*---------------------------------------------------------------------------*/
  640.  
  641. static void fixpasswd()
  642. {
  643.  
  644.   FILE * fp;
  645.   struct passwd *pp;
  646.   struct user *up;
  647.  
  648.   fp = fopenexcl(passtemp);
  649.   while ((pp = getpwent()) != NULL) {
  650.     if (is_call(pp->pw_name) && (up = getup(pp->pw_name, 0)) != NULL)
  651.       pp->pw_gecos = (char *) up->name;
  652.     putpwent(pp, fp);
  653.   }
  654.   endpwent();
  655.   fclose(fp);
  656. #ifdef __TURBOC__
  657.   unlink(passfile);
  658. #endif
  659.   unlink(passfile);
  660.   if (rename(passtemp, passfile)) terminate(passfile);
  661.   lockfile = NULL;
  662. }
  663.  
  664. /*---------------------------------------------------------------------------*/
  665.  
  666. static void fixaliases()
  667. {
  668.  
  669.   FILE * fpi, *fpo;
  670.   char  *p;
  671.   char  line[1024];
  672.   int  i;
  673.   struct user *up;
  674.  
  675.   if (!(fpi = fopen(aliasfile, "r"))) terminate(aliasfile);
  676.   fpo = fopenexcl(aliastemp);
  677.   while (fgets(line, sizeof(line), fpi)) {
  678.     if (!strncmp(line, "# Generated", 11)) break;
  679.     fputs(line, fpo);
  680.     if (isspace(uchar(*line))) continue;
  681.     if ((p = strchr(line, '#')) != NULL) *p = '\0';
  682.     if (!(p = strchr(line, ':'))) continue;
  683.     while (--p >= line && isspace(uchar(*p))) ;
  684.     p[1] = '\0';
  685.     if ((up = getup(line, 0)) != NULL) up->alias = 1;
  686.   }
  687.   fclose(fpi);
  688.   fputs("# Generated aliases\n", fpo);
  689.   for (i = 0; i < NUM_USERS; i++)
  690.     for (up = users[i]; up; up = up->next)
  691.       if (!up->alias && *up->mail)
  692.         if (*up->mail == '@')
  693.           fprintf(fpo, "%s\t\t: %s%s\n", up->call, up->call, up->mail);
  694.         else
  695.           fprintf(fpo, "%s\t\t: %s\n", up->call, up->mail);
  696.   fclose(fpo);
  697. #ifdef __TURBOC__
  698.   unlink(aliasfile);
  699. #endif
  700.   unlink(aliasfile);
  701.   if (rename(aliastemp, aliasfile)) terminate(aliasfile);
  702.   lockfile = NULL;
  703. }
  704.  
  705. /*---------------------------------------------------------------------------*/
  706.  
  707. int  main()
  708. {
  709.  
  710.   null_user.next = 0;
  711.   null_user.call = null_string;
  712.   null_user.name = null_string;
  713.   null_user.street = null_string;
  714.   null_user.city = null_string;
  715.   null_user.qth = null_string;
  716.   null_user.phone = null_string;
  717.   null_user.mail = null_string;
  718.   null_user.alias = 0;
  719.  
  720.   umask(022);
  721.   uname(&uts_name);
  722.   if (!fixusers()) {
  723.     fixpasswd();
  724.     /* fixaliases();  */
  725. #if (!DEBUG && !defined(__TURBOC__))
  726.     /* system("exec /usr/bin/newaliases >/dev/null 2>&1");  */
  727. #endif
  728.   }
  729.  
  730. #if DEBUG
  731.   fprintf(stderr, "Total heap size = %ld Bytes\n", heapsize);
  732. #endif
  733.  
  734.   return 0;
  735. }
  736.  
  737.